package utils

import (
	"encoding/base64"
	"encoding/json"
	"fastdp-ops/pkg/server/api/models"
	"fastdp-ops/pkg/server/config"
	"fmt"
	"html/template"
	"os"
	"reflect"
	"strings"
	"time"
)

type repoConfig struct {
	repoType string // repository_type（rpms/debs）
	osSubdir string // repo_os_type（如ubuntu2204、centos7等）
}

func CollectMachineVariables(host string, machine models.Machines, params map[string]string) (map[string]interface{}, error) {
	vars := map[string]interface{}{
		"IP":        host,
		"Machine":   machine,
		"Params":    params,
		"Timestamp": time.Now().Unix(),
	}
	var osRepoMap = map[string]repoConfig{
		"ubuntu":  {repoType: "debs", osSubdir: "ubuntu2204"},
		"centos":  {repoType: "rpms", osSubdir: "centos7"},
		"kylin":   {repoType: "rpms", osSubdir: "KylinV10"},
		"red hat": {repoType: "rpms", osSubdir: "rhel9"},
		"rocky":   {repoType: "rpms", osSubdir: "rocky9"},
	}
	lowerOSName := strings.ToLower(machine.OSName)
	for keyword, config := range osRepoMap {
		if strings.Contains(lowerOSName, keyword) {
			vars["repository_type"] = config.repoType
			vars["osSubdir"] = config.osSubdir
			break // 找到匹配项后退出循环
		}
	}
	listen := config.V.GetString("fastdp-ops.listen")
	vars["server_ip"] = listen
	port := config.V.GetString("fastdp-ops.port")
	vars["server_port"] = port
	// 可扩展：从数据库查询其他变量（如集群信息、应用配置等）
	// 示例：查询该主机所属的集群信息
	// cluster, err := getClusterInfo(machine.ClusterID)
	// if err != nil {
	//     return nil, err
	// }
	// vars["Cluster"] = cluster
	/*
		模板中可使用的变量示例：
			{{.IP}} → 目标机器IP
			{{.Machine.Hostname}} → 数据库中的主机名
			{{.Params.env}} → 透传的参数
			{{.Timestamp}} → 渲染时的时间戳
	*/

	return vars, nil
}
func RenderParams(params map[string]string, vars map[string]interface{}) (map[string]string, error) {
	var result = make(map[string]string)

	// 定义自定义模板函数映射
	funcMap := template.FuncMap{
		// lookup 函数：读取文件内容
		"lookup": func(path string) (string, error) {
			content, err := os.ReadFile(path)
			if err != nil {
				return "", fmt.Errorf("读取文件 %s 失败: %w", path, err)
			}
			return string(content), nil
		},
		// b64encode 函数：Base64编码
		"b64encode": func(input string) string {
			return base64.StdEncoding.EncodeToString([]byte(input))
		},
		// 新增lower函数：将字符串转为小写
		"lower": func(s string) string {
			return strings.ToLower(s)
		},
	}

	for k, v := range params {
		// 创建模板并注册自定义函数
		tpl, err := template.New("params-render").Funcs(funcMap).Parse(v)
		if err != nil {
			return nil, fmt.Errorf("解析参数模板 %s 失败: %w", k, err)
		}
		// 执行模板渲染
		var rendered strings.Builder
		if err := tpl.Execute(&rendered, vars); err != nil {
			return nil, fmt.Errorf("渲染参数 %s 失败: %w", k, err)
		}
		result[k] = rendered.String()
	}
	return result, nil
}
func RenderWhen(when string, vars map[string]interface{}) (string, error) {

	tpl, err := template.New("when-render").Parse(when)
	if err != nil {
		return "", fmt.Errorf("渲染when参数变量 %s 失败: %w", when, err)
	}
	var rendered strings.Builder
	if err = tpl.Execute(&rendered, vars); err != nil {
		return "", fmt.Errorf("渲染when参数变量 %s 失败: %w", when, err)
	}
	result := rendered.String()

	return result, nil
}
func MergeVariables(global map[string]interface{}, local map[string]interface{}, roles map[string][]string) map[string]interface{} {
	// 初始化合并后的上下文，先复制全局变量
	merged := make(map[string]interface{})
	for k, v := range global {
		merged[k] = v
	}
	// 用局部变量覆盖全局变量（局部变量优先级更高）
	for k, v := range local {
		merged[k] = v
	}
	merged["Roles"] = roles
	return merged
}

// 替换原有的RenderLoopVariable函数
func RenderLoopVariable(loopVars []string, vars map[string]interface{}) ([]interface{}, error) {
	var result []interface{}
	for _, loopExpr := range loopVars {
		// 解析表达式（如 ".Roles.k8s_cluster" 或直接字符串 "192.168.1.101"）
		// 先判断是否是模板表达式（包含{{}}）
		if strings.HasPrefix(loopExpr, "{{") && strings.HasSuffix(loopExpr, "}}") {
			// 去除模板标签，提取表达式（如 "{{.Roles.k8s_cluster}}" → ".Roles.k8s_cluster"）
			expr := strings.TrimSpace(loopExpr[2 : len(loopExpr)-2])
			if expr == "" {
				return nil, fmt.Errorf("模板表达式不能为空: %s", loopExpr)
			}
			// 从vars中获取原始值（支持嵌套结构）
			val, err := getNestedValue(vars, expr)
			if err != nil {
				return nil, fmt.Errorf("解析循环表达式 %s 失败: %w", loopExpr, err)
			}
			// 如果是切片或数组，展开添加到结果
			if reflect.TypeOf(val).Kind() == reflect.Slice || reflect.TypeOf(val).Kind() == reflect.Array {
				valSlice := reflect.ValueOf(val)
				for i := 0; i < valSlice.Len(); i++ {
					result = append(result, valSlice.Index(i).Interface())
				}
			} else {
				// 非切片类型，直接添加
				result = append(result, val)
			}
		} else if strings.HasPrefix(loopExpr, "{") && strings.HasSuffix(loopExpr, "}") {
			var jsonData map[string]string
			if err := json.Unmarshal([]byte(loopExpr), &jsonData); err != nil {
				return nil, fmt.Errorf("解析JSON表达式 %s 失败: %w", loopExpr, err)
			}
			if len(jsonData) == 0 {
				return nil, fmt.Errorf("JSON表达式不能为空对象: %s", loopExpr)
			}
			result = append(result, jsonData)
			// 3. 普通字符串（非模板非JSON）
		} else {
			// 非模板表达式，直接作为字符串元素
			result = append(result, loopExpr)
		}
	}
	return result, nil
}

// 辅助函数：获取嵌套变量的值（如从vars中获取 ".Roles.k8s_cluster" 的值）
func getNestedValue(vars map[string]interface{}, expr string) (interface{}, error) {
	fmt.Println(vars["Kylin_V10_pkg"])
	parts := strings.Split(expr, ".")
	if len(parts) == 0 || parts[0] != "" {
		return nil, fmt.Errorf("表达式格式错误: %s", expr)
	}
	// 从根节点开始遍历（parts[0]是空字符串，parts[1]是第一个键）
	current := vars
	for i := 1; i < len(parts); i++ {
		key := parts[i]
		val, ok := current[key]
		if !ok {
			return nil, fmt.Errorf("变量 %s 不存在", strings.Join(parts[:i+1], "."))
		}
		// 如果是map，继续深入；否则返回当前值
		if m, ok := val.(map[string]interface{}); ok {
			current = m
			continue
		}
		// 如果是最后一个键，返回值；否则报错（非map类型无法继续深入）
		if i == len(parts)-1 {
			return val, nil
		}
		return nil, fmt.Errorf("变量 %s 不是map类型，无法访问 %s", strings.Join(parts[:i+1], "."), key)
	}
	return current, nil
}
